// #pragma once
#ifndef __RingQueue_H__
#define __RingQueue_H__
#include <pthread.h>
#include <string>
#include <semaphore.h>
#include <vector>

static const int defaultcap = 5;
//多生产多消费

//使用信号量
template<class T>
class RingQueue
{
    //申请信号量
    void P(sem_t &sem)
    {
        sem_wait(&sem);
    }
    //释放信号量
    void V(sem_t &sem)
    {
        sem_post(&sem);
    }

    void lock(pthread_mutex_t &lock)
    {
        pthread_mutex_lock(&lock);
    }

    void unlock(pthread_mutex_t &lock)
    {
        pthread_mutex_unlock(&lock);
    }
public:
    RingQueue(int cap = defaultcap):_cap(cap), _RQ(_cap), _pse(0), _cda(0)
    {
        sem_init(&_pSpace, 0, _cap);
        sem_init(&_cData, 0, 0);

        pthread_mutex_init(&_clock, nullptr);
        pthread_mutex_init(&_plock, nullptr);
    }

    //生产
    void push(T& in)
    {
        P(_pSpace);

        lock(_plock);
        _RQ[_pse] = in;
        _pse++;
        //一直循环
        _pse %= _cap;
        unlock(_plock);

        V(_cData);
    }

    //消费
    void pop(T *out)
    {
        P(_cData);

        lock(_clock);
        *out = _RQ[_cda];
        _cda++;
        //一直循环
        _cda %= _cap;
        unlock(_clock);

        V(_pSpace);
    }

    ~RingQueue()
    {
        sem_destroy(&_pSpace);
        sem_destroy(&_cData);

        pthread_mutex_destroy(&_clock);
        pthread_mutex_destroy(&_plock);
    }

private:
    int _cap;
    std::vector<T> _RQ;

    //下标，资源数量
    int _pse; //生产者下标
    int _cda; //消费者下标

    sem_t _pSpace; //生产者空间资源
    sem_t _cData; //消费者数据资源

    pthread_mutex_t _plock;
    pthread_mutex_t _clock;
};

#endif  

// //使用信号量
// template<class T>
// class RingQueue
// {
//     //申请信号量
//     void P(sem_t &sem)
//     {
//         sem_wait(&sem);
//     }
//     //释放信号量
//     void V(sem_t &sem)
//     {
//         sem_post(&sem);
//     }

// public:
//     RingQueue(int cap):_cap(cap), _RQ(_cap), _pse(0), _cda(0)
//     {
//         sem_init(&_pSpace, 0, _cap);
//         sem_init(&_cData, 0, 0);
//     }

//     //生产
//     void push(T& in)
//     {
//         P(_pSpace);
//         _RQ[_pse] = in;
//         V(_cData);

//         _pse++;
//         //一直循环
//         _pse %= _cap;
//     }

//     //消费
//     void pop(T *out)
//     {
//         P(_cData);
//         *out = _RQ[_cda];
//         V(_pSpace);

//         _cda++;
//         //一直循环
//         _cda %= _cap;
//     }

//     ~RingQueue()
//     {
//         sem_destroy(&_pSpace);
//         sem_destroy(&_cData);
//     }

// private:
//     int _cap;
//     std::vector<T> _RQ;

//     //下标，资源数量
//     int _pse;
//     int _cda;

//     sem_t _pSpace;
//     sem_t _cData;
// };

// #endif  